package cn.songtx.iot.service.impl;

import cn.songtx.iot.mapper.SysEquipmentMapper;
import cn.songtx.iot.mapper.SysFamilyMapper;
import cn.songtx.iot.mapper.SysRoomMapper;
import cn.songtx.iot.mapper.SysUserFamilyMapper;
import cn.songtx.iot.pojo.*;
import cn.songtx.iot.service.ISysEquipmentService;
import cn.songtx.iot.vo.FamilyRoomEquipmentVO;
import cn.songtx.iot.vo.RoomEquipmentVO;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/*
 * 自定义实现继承ServiceImpl<Mapper,T>实现类,实现IService接口,在<>定义了需要调用的Mapper和范型
 * 使用@Service注解
 * */
@Service
@DS("master")     // 指定数据源,strict: false时,缺省使用master库
public class SysEquipmentServiceImpl extends ServiceImpl<SysEquipmentMapper, SysEquipment> implements ISysEquipmentService {

    @Autowired
    SysUserFamilyMapper sysUserFamilyMapper;
    @Autowired
    SysFamilyMapper sysFamilyMapper;
    @Autowired
    SysRoomMapper sysRoomMapper;

    /**
     * 自定义Service接口,设备查询,管理查询接口
     * 1. 用 user_id 查询 sys_family 表,返回 List<SysFamily>
     * 2. 用 familyIds 查询 sys_room 表,返回 List<SysRoom>
     * 3. 用 roomIds 查询 sys_equipment 表,返回 List<equipment>
     * 4. 3层对象数组嵌套 family->room->equipment
     *
     * @param sysUserId 用户id
     * @return VO
     */
    @Override
    public List<FamilyRoomEquipmentVO> selectFamilyRoomEquipmentByOwner(Long sysUserId) {
        // 0. 创建3层嵌套的FamilyRoomEquipmentVO
        List<FamilyRoomEquipmentVO> familyRoomEquipmentVOS = new ArrayList<>();

        // 1. 第一次查询,根据 userId 查询 sys_family 表,返回 List<SysFamily>
        LambdaQueryWrapper<SysFamily> sysFamilyLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysFamilyLambdaQueryWrapper.select(SysFamily::getId, SysFamily::getFamilyName, SysFamily::getInformation, SysFamily::getSysUserId)
                .eq(SysFamily::getSysUserId, sysUserId);
        List<SysFamily> sysFamilyList = sysFamilyMapper.selectList(sysFamilyLambdaQueryWrapper);
        // 2. 从返回的对象中获取id,stream的map操作
        List<Long> family_ids = sysFamilyList.stream().map(SysFamily::getId).toList();

        // 3. 第二次查询,family_ids 查询 sys_room 表,返回 List<SysRoom>
        LambdaQueryWrapper<SysRoom> roomLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roomLambdaQueryWrapper.select(SysRoom::getId, SysRoom::getRoomName, SysRoom::getInformation, SysRoom::getFamilyId)
                .in(SysRoom::getFamilyId, family_ids);
        List<SysRoom> roomList = sysRoomMapper.selectList(roomLambdaQueryWrapper);
        // 3.1 从返回的对象中获取id,stream的map操作
        List<Long> room_ids = roomList.stream().map(SysRoom::getId).toList();

        // 4. 第三次查询,room_ids 查询 sys_equipment 表,返回 List<equipment>
        LambdaQueryWrapper<SysEquipment> equipmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        equipmentLambdaQueryWrapper.in(SysEquipment::getRoomId, room_ids);
        List<SysEquipment> sysEquipmentList = this.list(equipmentLambdaQueryWrapper);

        // 5. 创建2层嵌套的RoomEquipmentVO
        List<RoomEquipmentVO> roomEquipmentVOS = new ArrayList<>();
        // 5.1 sysRoom数据拷贝到roomEquipmentVO的第一层
        for (SysRoom sysRoom : roomList) {
            RoomEquipmentVO roomEquipmentVO = new RoomEquipmentVO();
            BeanUtils.copyProperties(sysRoom, roomEquipmentVO);
            roomEquipmentVOS.add(roomEquipmentVO);
        }
        // 5.2 sysEquipmentList数据按照roomId分组
        Map<Long, List<SysEquipment>> collectRoomId = sysEquipmentList.stream()
                .collect(Collectors.groupingBy(SysEquipment::getRoomId));
        // 5.3 分组后的equipment数据拷贝到roomEquipmentVO的第二层
        for (RoomEquipmentVO roomEquipmentVO : roomEquipmentVOS) {
            roomEquipmentVO.setEquipments(collectRoomId.get(roomEquipmentVO.getId()));
        }

        // 5.4 roomEquipmentVO再分组
        Map<Long, List<RoomEquipmentVO>> collectFamily = roomEquipmentVOS.stream().collect(Collectors.groupingBy(RoomEquipmentVO::getFamilyId));
        // 5.5 family数据拷贝到familyRoomEquipmentVO的第一层
        for (SysFamily sysFamily : sysFamilyList) {
            FamilyRoomEquipmentVO familyRoomEquipmentVO = new FamilyRoomEquipmentVO();
            BeanUtils.copyProperties(sysFamily, familyRoomEquipmentVO);
            familyRoomEquipmentVOS.add(familyRoomEquipmentVO);
        }
        // 5.6 分组后的familyRoomEquipment再拷贝到FamilyRoomEquipmentVO的第二层
        for (FamilyRoomEquipmentVO familyRoomEquipmentVO : familyRoomEquipmentVOS) {
            familyRoomEquipmentVO.setRooms(collectFamily.get(familyRoomEquipmentVO.getId()));
        }

        return familyRoomEquipmentVOS;
    }

    /**
     * 自定义Service接口,设备查询,用户查询接口
     * 0. 创建VO
     * 1. user_id 查询 sys_user_family 中间表,返回 List<SysFamily>
     * 2. List<family_ids> 查询 sys_family 表,用于 PO->VO
     * 3. family_ids 查询 sys_room 表,返回 List<room_ids>
     * 4. room_ids 查询sys_equipment 表,返回 List<equipment>
     * 5. 3层对象数组嵌套 family->room->equipment,分两次嵌套
     *
     * @param sysUserId 用户id
     * @return VO
     */
    @Override
    public List<FamilyRoomEquipmentVO> selectFamilyRoomEquipmentByUser(Long sysUserId) {
        // 0. 创建3层嵌套的FamilyRoomEquipmentVO
        List<FamilyRoomEquipmentVO> familyRoomEquipmentVOS = new ArrayList<>();

        // 1. 第一次查询,根据 userId 查询 sys_user_family 表(中间表),返回 List<SysUserFamily>
        LambdaQueryWrapper<SysUserFamily> sysUserFamilyLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysUserFamilyLambdaQueryWrapper.select(SysUserFamily::getFamilyId)
                .eq(SysUserFamily::getUserId, sysUserId);
        List<SysUserFamily> userFamilyList = sysUserFamilyMapper.selectList(sysUserFamilyLambdaQueryWrapper);

        // 1.1 从返回的对象中获取 familyIds,stream 的 map 操作
        List<Long> family_ids = userFamilyList.stream().map(SysUserFamily::getFamilyId).toList();

        // 2. 第二次查询,根据 familyIds 查询 sys_family 表,返回 List<family>,用于PO->VO,这里的id指的是主键id
        LambdaQueryWrapper<SysFamily> sysFamilyLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysFamilyLambdaQueryWrapper.select(SysFamily::getId, SysFamily::getFamilyName, SysFamily::getInformation)
                .in(SysFamily::getId, family_ids);
        List<SysFamily> sysFamilyList = sysFamilyMapper.selectList(sysFamilyLambdaQueryWrapper);

        // 3. 第三次查询,family_ids 查询 sys_room 表,返回room_ids
        LambdaQueryWrapper<SysRoom> roomLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roomLambdaQueryWrapper.select(SysRoom::getId, SysRoom::getRoomName, SysRoom::getInformation, SysRoom::getFamilyId)
                .in(SysRoom::getFamilyId, family_ids);
        List<SysRoom> roomList = sysRoomMapper.selectList(roomLambdaQueryWrapper);
        // 3.1 从返回的对象中获取id,stream的map操作
        List<Long> room_ids = roomList.stream().map(SysRoom::getId).toList();

        // 4. 第四次查询,room_ids 查询 sys_equipment 表,返回 List<equipment>
        LambdaQueryWrapper<SysEquipment> equipmentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        equipmentLambdaQueryWrapper.in(SysEquipment::getRoomId, room_ids);
        List<SysEquipment> sysEquipmentList = this.list(equipmentLambdaQueryWrapper);

        // 5. 创建2层嵌套的RoomEquipmentVO
        List<RoomEquipmentVO> roomEquipmentVOS = new ArrayList<>();
        // 5.1 sysRoom数据拷贝到roomEquipmentVO的第一层
        for (SysRoom sysRoom : roomList) {
            RoomEquipmentVO roomEquipmentVO = new RoomEquipmentVO();
            BeanUtils.copyProperties(sysRoom, roomEquipmentVO);
            roomEquipmentVOS.add(roomEquipmentVO);
        }
        // 5.2 sysEquipmentList数据按照roomId分组
        Map<Long, List<SysEquipment>> collectRoomId = sysEquipmentList.stream()
                .collect(Collectors.groupingBy(SysEquipment::getRoomId));
        // 5.3 分组后的equipment数据拷贝到roomEquipmentVO的第二层
        for (RoomEquipmentVO roomEquipmentVO : roomEquipmentVOS) {
            roomEquipmentVO.setEquipments(collectRoomId.get(roomEquipmentVO.getId()));
        }

        // 5.4 roomEquipmentVO再分组
        Map<Long, List<RoomEquipmentVO>> collectFamily = roomEquipmentVOS.stream().collect(Collectors.groupingBy(RoomEquipmentVO::getFamilyId));
        // 5.5 family数据拷贝到familyRoomEquipmentVO的第一层
        for (SysFamily sysFamily : sysFamilyList) {
            FamilyRoomEquipmentVO familyRoomEquipmentVO = new FamilyRoomEquipmentVO();
            BeanUtils.copyProperties(sysFamily, familyRoomEquipmentVO);
            familyRoomEquipmentVOS.add(familyRoomEquipmentVO);
        }
        // 5.6 分组后的familyRoomEquipment再拷贝到FamilyRoomEquipmentVO的第二层
        for (FamilyRoomEquipmentVO familyRoomEquipmentVO : familyRoomEquipmentVOS) {
            familyRoomEquipmentVO.setRooms(collectFamily.get(familyRoomEquipmentVO.getId()));
        }
        return familyRoomEquipmentVOS;
    }
}
